iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Security

一起資安入門 -- picoCTF 探索與解題系列 第 21

[2021鐵人賽 Day21] General Skills 18

  • 分享至 

  • xImage
  •  
  • 引言
    今天是我們 General Skills 最後一題,光是基礎技能我們就花了 21 天呢...
    畢竟是入門,我們就慢慢來吧!
    明天開始會花一天介紹一下 2019 的遊戲,之後就是六個領域各選一至兩題來解囉!

    這題算是 General Skills 中技術含量較高的,也需要一點點 C 語言基礎,
    非常適合當壓軸~/images/emoticon/emoticon12.gif我們開始吧!

  • General Skills / flag_shop
    https://ithelp.ithome.com.tw/upload/images/20211006/20111429QhuxjB3MFU.png
    這題的情境是說有個商店會販賣 flag ,買到你就有 flag 了~
    題目給的材料除了商店程式所在伺服器以外,還罕見地給了商店程式的原始碼,用 C 語言寫的!
    總之我們先把原始碼下載下來等等備用,檔案名稱是 store.c

    我們先不看原始碼,先用 nc 玩玩 flag 商店是怎麼運作的:

    $ nc jupiter.challenges.picoctf.org 4906
    

    連上後程式輸出:

    Welcome to the flag exchange
    We sell flags
    
    1. Check Account Balance
    
    2. Buy Flags
    
    3. Exit
    
     Enter a menu selection
    

    看起來是 menu 形式的界面,可以輸入 1,2,3 來決定需要什麼服務。
    1 是查看帳戶餘額, 2 是買 flag , 3 是離開,
    總之我們先看看目前的餘額,輸入 1 按下 Enter :

    
    
    
     Balance: 1100 
    
    
    Welcome to the flag exchange
    We sell flags
    
    1. Check Account Balance
    
    2. Buy Flags
    
    3. Exit
    
     Enter a menu selection
    

    可以看到餘額是 1100 ,再來我們試著購買 flag 看看,輸入 2 :

    Currently for sale
    1. Defintely not the flag Flag
    2. 1337 Flag
    

    它販賣兩種 flag ,一個是「絕對不是 flag 的 flag 」,另一個是「 1337 flag 」,
    先看看 1337 flag 吧:

    1337 flags cost 100000 dollars, and we only have 1 in stock
    Enter 1 to buy one
    

    居然需要十萬,而且只有一個,想必這就是解答 flag 了,我們看另一個 flag 是什麼:

    These knockoff Flags cost 900 each, enter desired quantity
    

    它說仿冒品只要 900 ,輸入你要的數量。如果你真的買了什麼事都不會發生~
    先 ctrl-C 或是第三個選項離開程式吧,等等找到方法後要重開。

    總結來說目前正常使用是買不到十萬 flag 的,我們看看原始碼有什麼,
    這是 C 語言程式,我等一下只講一下關鍵部份,大家可以先自己找找看突破點在哪裡,
    提示是「條件、上限」。


    
    解
    
    答
    
    在
    
    下
    
    面
    
    

    其實關鍵在 C 語言 int 的數值上限 ,最高是 2147483647 ,也就是 2 的 31 次方 - 1 ,
    最高的正數只能到這,一旦再 + 1 ,你會發現變數內容變成 -2147483648 ,這兩數可是天差地遠的!
    這個程式的漏洞在:

    int number_flags = 0;
    fflush(stdin);
    scanf("%d", &number_flags);
    if(number_flags > 0){
        int total_cost = 0;
        total_cost = 900*number_flags;  // <-- 漏洞
        printf("\nThe final cost is: %d\n", total_cost);
        if(total_cost <= account_balance){  // <-- 造成這邊可以穿過去
            account_balance = account_balance - total_cost;  // <-- 幫你加錢
            printf("\nYour current balance after transaction: %d\n\n", account_balance);
        }
        else{
            printf("Not enough funds to complete purchase\n");
        }
    
    
    }
    

    當你輸入了 number_flag ,雖然有個 if(number_flags > 0) 讓你無法輸入負數,
    但是在我標注漏洞的地方,它把這個數字乘以 900 ,所以如果你 number_flag 很大,
    大到一定程度但不會超過上限,這時 if(number_flags > 0) 你可以順利通過,
    但下面會乘以 900 ,如果你輸入的數乘以 900 超過 2147483647 , bug 就出現了,
    total_cost 會變成負的,那我標注的地方就可以穿過去,下面就會幫你加錢!

    所以我們破解的方法,就是輸入一個很大的數,
    大概就是乘以 900 後超出 2147483647 一兩千的程度,
    因為超出範圍後會從 -2147483648 開始往上加,
    -2147483647,
    -2147483646,
    ...
    而原本餘額有 1100 ,所以我們要抓超出上限大概 1000 多,
    才能加上去以後不至於又爆掉:

    account_balance = account_balance - total_cost;
    

    看上面的那句,如果 total_cost 變成 -2147482000 左右 (大概超出上限一兩千會變這樣)
    那 1100 - (-2147482000) = 2147483100 ,很剛好不超過 account_balance 的上限。

    因此,我們的目標就是「 900 x 輸入的值 = 2147483647大概再超出2000 」,
    定量來說,我把輸入的值取: 2147485647 / 900 ~= 2386095 ,估計會得到幾乎最多的錢,
    試試看:

    Currently for sale
    1. Defintely not the flag Flag
    2. 1337 Flag
    1
    These knockoff Flags cost 900 each, enter desired quantity
    2386095
    

    輸入我要買 2386095 個冒牌貨 flag :

    
    The final cost is: -2147481796
    
    Your current balance after transaction: 2147482896
    

    厲害了,你花了 -2147481796 個錢,餘額剩下 2147482896 ,
    真的相當接近最大值。

    我們可以買 flag 啦,而且錢綽綽有餘呢:

    Currently for sale
    1. Defintely not the flag Flag
    2. 1337 Flag
    2
    1337 flags cost 100000 dollars, and we only have 1 in stock
    Enter 1 to buy one1
    YOUR FLAG IS: picoCTF{m0n3y_bag5_9c5fac9b}
    

    購買 1337 flag ,輸入 1 買一個,
    就得到 flag 啦!


上一篇
[2021鐵人賽 Day20] General Skills 17
下一篇
[2021鐵人賽 Day22] picoCTF 2019 Game 遊玩介紹
系列文
一起資安入門 -- picoCTF 探索與解題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言